﻿namespace IOCDemo.IocVersion2;

public class ContainerBuilder
{
    private IServiceCollection _serviceDescriptors;

    public ContainerBuilder()
    {
        _serviceDescriptors = new ServiceCollection();
    }

    public void RegisterType<TService>(LifeTimeType lifeTimeType = LifeTimeType.Normal) where TService : class
    {
        _serviceDescriptors.Add(new ServiceDescriptor(typeof(TService), lifeTimeType));
    }

    /// <summary>
    /// 注册
    /// </summary>
    /// <param name="tag"></param>
    /// <param name="lifeTimeType"></param>
    /// <typeparam name="IService">源类型(接口)</typeparam>
    /// <typeparam name="TService">目标类</typeparam>
    public void RegisterType<IService, TService>(string tag, LifeTimeType lifeTimeType = LifeTimeType.Normal)
        where TService : class
    {
        _serviceDescriptors.Add(new ServiceDescriptor(typeof(IService), typeof(TService), lifeTimeType, tag));
    }

    /// <summary>
    /// 注册
    /// </summary>
    /// <param name="lifeTimeType"></param>
    /// <typeparam name="IService">源类型(接口)</typeparam>
    /// <typeparam name="TService">目标类</typeparam>
    public void RegisterType<IService, TService>(LifeTimeType lifeTimeType = LifeTimeType.Normal) where TService : class
    {
        _serviceDescriptors.Add(new ServiceDescriptor(typeof(IService), typeof(TService), lifeTimeType));
    }

    public void AutoRegisterIoc()
    {
        var assemblies = AppDomain.CurrentDomain.GetAssemblies();
        foreach (var item in assemblies)
        {
            if (item.FullName.Contains("System"))
            {
                continue;
            }

            var types = item.GetTypes();
            Func<Attribute[], bool> IsHaveAutoIocAttribute = o =>
            {
                foreach (var attribute in o)
                {
                    if (attribute is AutoIocAttribute)
                    {
                        return true;
                    }
                }

                return false;
            };

            foreach (var type in types)
            {
                if (IsHaveAutoIocAttribute(Attribute.GetCustomAttributes(type, true)))
                {
                    var attribute = (AutoIocAttribute)Attribute.GetCustomAttribute(type, typeof(AutoIocAttribute));
                    if (attribute.RelationClassType == null)
                    {
                        _serviceDescriptors.Add(new ServiceDescriptor(type, attribute.Model));
                    }
                    else
                    {
                        _serviceDescriptors.Add(new ServiceDescriptor(type, attribute.RelationClassType,
                            attribute.Model));
                        if (attribute.Model == LifeTimeType.Singleton)
                        {
                            // AbsoluteSingleRegister(attribute.RelationClassType);
                        }
                    }
                }
            }
        }
    }

    public IContainer Build()
    {
        foreach (var item in _serviceDescriptors)
        {
            foreach (var constructor in item.Constructors)
            {
                bool isDefault = item.Default == null;
                foreach (var info  in constructor.ParameterInfos)
                {
                    var descriptor = _serviceDescriptors.First(x => x.Source == info.ParameterType);
                    if (descriptor == null)
                    {
                        isDefault = false;
                        continue;
                    }
                    item.DependServices.Add(descriptor);
                }

                if (isDefault)
                {
                    item.Default = constructor;
                }
            }
        }

        return new Container(_serviceDescriptors);
    }
}